package org.finesys.common.netty.websocket.util;

import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ResourceUtils;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManagerFactory;
import java.net.URL;
import java.security.KeyStore;

/**
 * SSL 认证工具类
 */
public class SslUtils {

    public static SslContext createSslContext(String keyPassword, String keyStoreResource, String keyStoreType,
                                              String keyStorePassword, String trustStoreResouce,
                                              String trustStoreType, String trustStorePassword) throws SSLException {
        SslContextBuilder sslContextBuilder = SslContextBuilder.forServer(getKeyManagerFactory(keyStoreType, keyStoreResource, keyPassword, keyStorePassword))
                .trustManager(getTrustManagerFactory(trustStoreType, trustStoreResouce, trustStorePassword));
        return sslContextBuilder.build();
    }


    private static KeyManagerFactory getKeyManagerFactory(String keyStoreType, String keyStoreResource, String keyPassword, String keyStorePassword) {
        try {
            KeyStore keyStore = loadKeyStore(keyStoreType, keyStoreResource, keyStorePassword);
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            char[] keyPasswordBytes = (!ObjectUtils.isEmpty(keyPassword) ? keyPassword.toCharArray() : null);
            if (keyPasswordBytes == null && !ObjectUtils.isEmpty(keyStorePassword)) {
                keyPasswordBytes = keyStorePassword.toCharArray();
            }
            keyManagerFactory.init(keyStore, keyPasswordBytes);
            return keyManagerFactory;
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
    }

    private static TrustManagerFactory getTrustManagerFactory(String trustStoreType, String trustStoreResouce, String trustStorePassword) {
        try {
            KeyStore keyStore = loadKeyStore(trustStoreType, trustStoreResouce, trustStorePassword);
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            return trustManagerFactory;
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
    }


    private static KeyStore loadKeyStore(String type, String resource, String password) throws Exception {
        type = (ObjectUtils.isEmpty(type) ? "JKS" : type);
        if (ObjectUtils.isEmpty(resource)) {
            return null;
        }
        KeyStore keyStore = KeyStore.getInstance(type);
        URL url = ResourceUtils.getURL(resource);
        keyStore.load(url.openStream(), ObjectUtils.isEmpty(password) ? null : password.toCharArray());
        return keyStore;
    }
}